# @Version        : 1.0
# @Update Time    : 2025/9/15 22:04
# @File           : permission.py
# @IDE            : PyCharm
# @Desc           : 文件描述信息
from typing import Literal, Optional

from fastapi import HTTPException, Request, Security

from authx.dependencies.helpers import ensure_login
from authx.dependencies.oauth2 import oauth2_required


class PermissionChecker:
    """权限校验依赖类 - 支持单权限或多权限组合校验及多用户类型"""

    def __init__(
        self,
        *permissions: str,
        logic: Literal["and", "or"] = "and",
        user_type: str = "login",
    ):
        """初始化权限校验器

        Args:
            *permissions: 一个或多个权限字符串
            logic: 权限组合逻辑，可选值为 "and" 或 "or"，默认为 "and"
            user_type: 用户类型，默认为 "login"
        """

        self.permissions = permissions
        self.logic = logic
        # 验证用户类型
        if isinstance(user_type, str) and user_type.strip() != "":
            self.user_type = user_type.strip()
        else:
            self.user_type = "login"

    async def __call__(
        self, request: Request, token: str = Security(oauth2_required)
    ) -> str:
        if not token:
            raise HTTPException(status_code=401, detail="未登录")
        auth_logic, login_id, is_admin = await ensure_login(
            request, self.user_type, token
        )
        # 是否禁用
        if await auth_logic.is_disable(login_id=login_id):
            raise HTTPException(status_code=403, detail="用户被禁用")
        if is_admin or not self.permissions:
            return login_id
        if not await auth_logic.has_permission(*self.permissions, logic=self.logic):
            raise HTTPException(status_code=403, detail="无权限")
        return login_id


class RoleChecker:
    """角色校验依赖类 - 支持单角色或多角色组合校验及多用户类型"""

    def __init__(
        self,
        *roles: str,
        user_type: str = "login",
    ):
        """初始化角色校验器

        Args:
            *roles: 一个或多个角色字符串
            logic: 角色组合逻辑，可选值为 "and" 或 "or"，默认为 "and"
            user_type: 用户类型，默认为 UserType.DEFAULT
        """
        self.roles = roles
        # 验证用户类型
        if isinstance(user_type, str) and user_type.strip() != "":
            self.user_type = user_type.strip()
        else:
            self.user_type = "login"

    async def __call__(
        self, request: Request, token: Optional[str] = Security(oauth2_required)
    ) -> str:
        if not token:
            raise HTTPException(status_code=401, detail="未登录")
        auth_logic, login_id, is_admin = await ensure_login(
            request, self.user_type, token
        )
        if is_admin or not self.roles:
            return login_id
        if not await auth_logic.has_role(*self.roles):
            raise HTTPException(
                status_code=403, detail=f"缺少角色: {', '.join(self.roles)}"
            )
        return login_id
